package com.panopset.game.blackjack;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.panopset.compat.Strings;
import com.panopset.compat.Util;

/**
 * Card total.
 *
 * @author Karl Dinwiddie
 *
 */
public class Total {

    public boolean hasSplit = false;

    /**
     * 21, of course.
     */
    public final static int MAX = 21;

    /**
     * soft value.
     */
    private int sv = 0;

    /**
     * hard value.
     */
    private int hv = 0;

    /**
     * Cards.
     */
    public final Vector<BlackjackCard> cards = new Vector<BlackjackCard>();

    public synchronized List<BlackjackCard> getCardsCopy() {
        List<BlackjackCard> rtn = new ArrayList<BlackjackCard>();
        for (BlackjackCard c : cards) {
            rtn.add(c);
        }
        return rtn;
    }


    public synchronized int getHardValueOf(int i) {
        if (i < cards.size()) {
            return cards.get(i).getHardValue();
        }
        return -1;
    }


    public boolean isNatural21() {
        return isInitialDeal() && getValue() == 21;
    }


    public boolean isNaturalNonSplit() {
        return isNatural21() && !hasSplit;
    }

    public synchronized boolean hasCards() {
        return !cards.isEmpty();
    }

    public synchronized boolean isInitialHand() {
        return hasCards() && cards.size() == 2;
    }

    public synchronized BlackjackCard remove(int i) {
        return cards.remove(i);
    }

    public synchronized void setShowing(int i) {
        cards.get(i).show();
    }

    public synchronized BlackjackCard getUpCard() {
        if (cards.size() > 1) {
            return cards.get(1);
        }
        return null;
    }

    public synchronized boolean isEmpty() {
        return cards.isEmpty();
    }

    /**
     *
     * @param card
     *            Playing card.
     */
    public synchronized final void deal(final BlackjackCard card) {
        cards.add(card);
        boolean firstAceFound = false;
        sv = 0;
        hv = 0;
        for (BlackjackCard c : cards) {
            if (c.isAce()) {
                if (firstAceFound) {
                    sv = sv + c.getHardValue();
                    hv = hv + c.getHardValue();
                } else {
                    sv = sv + c.getSoftValue();
                    hv = hv + c.getHardValue();
                    firstAceFound = true;
                }
            } else {
                hv = hv + c.getHardValue();
                sv = sv + c.getHardValue();
            }
        }
        if (sv > MAX) {
            sv = hv;
        }
    }

    public boolean isDone() {
        return isBusted() || isSurrendered();
    }

    public boolean isBusted() {
        boolean rtn = sv > MAX;
        if (rtn) {
            stand();
        }
        return rtn;
    }

    public boolean isSoft() {
        return !(sv == hv);
    }

    public int getValue() {
        if (isSoft()) {
            return sv;
        } else {
            return hv;
        }
    }

    public void surrender() {
        surrendered = true;
        stand();
    }

    public void stand() {
        finalized = true;
    }

    private boolean finalized = false;

    private boolean surrendered = false;

    public boolean isFinal() {
        return finalized;
    }

    public boolean isSurrendered() {
        return surrendered;
    }

    public synchronized boolean isInitialDeal() {
        return cards.size() == 2;
    }
    public boolean isSplitable(BlackjackConfig c) {
        return !Strings.isPopulated(getCantSplitMessageIfCantSplit(c));
    }
    public synchronized String getCantSplitMessageIfCantSplit(BlackjackConfig c) {
        if (isInitialDeal()) {
            if (cards.get(0).getCard().getFace() == cards.get(1).getCard()
                    .getFace()) {
                if (cards.get(0).isAce() && hasSplit) {
                    if (c.isResplitAcesAllowed()) {
                        return "";
                    } else {
                        return Util.x("Resplit aces not allowed in this casino.");
                    }
                } else {
                    return "";
                }
            } else {
                return Util.x("Can only split matching cards.");
            }
        } else {
            return Util.x("Can only split two cards.");
        }
    }
}
